#include <iostream>
#include <memory>
#include <string>

// 抽象电脑类
class Computer{
public:
    void SetBoard(const std::string &board){
        _board = board;
    }
    void SetDisplay(const std::string &display){
        _display = display;
    }
    virtual void SetOs() = 0;
    std::string ToString(){
        std::string computer;
        computer += "Computer:{\n";
        computer += "\tboard=" + _board + ",\n";
        computer += "\tdisplay=" + _display + ",\n";
        computer += "\tOs=" + _os + ",\n";
        computer += "}\n";
        return computer;
    }

protected:
    std::string _board;
    std::string _display;
    std::string _os;
};

// 具体电脑产品类
class MacBook : public Computer{
public:
    void SetOs() override{
        _os = "Mac 12.0";
    }
};

// 抽象建造者类
class Builder{
public:
    virtual void BuildBoard(const std::string &board) = 0;
    virtual void BuildDisplay(const std::string &display) = 0;
    virtual void BuildOs() = 0;
    virtual std::shared_ptr<Computer> build() = 0;
};

// 具体电脑产品的具体建造者类
class MacBookBuilder : public Builder{
public:
    MacBookBuilder()
    :_computer(new MacBook())
    {}
    void BuildBoard(const std::string &board) override {
        _computer->SetBoard(board);
    }
    void BuildDisplay(const std::string &display) override {
        _computer->SetDisplay(display);
    }
    void BuildOs() override {
        _computer->SetOs();
    }
    std::shared_ptr<Computer> build() override {
        return _computer;
    }

private:
    std::shared_ptr<Computer> _computer;
};

// 建造者的管理者类
class Director{
public:
    Director(std::shared_ptr<Builder> builder)
    :_builder(builder)
    {}
    void construct(const std::string &board, const std::string &display){
        _builder->BuildBoard(board);
        _builder->BuildDisplay(display);
        _builder->BuildOs();
    }

private:
    std::shared_ptr<Builder> _builder;
};

int main(){
    std::shared_ptr<MacBookBuilder> mer(new MacBookBuilder()); // 创建一个苹果电脑的建造者对象
    std::shared_ptr<Director> dor(new Director(mer));          // 建造者对象交由管理者进行管理
    dor->construct("英特尔主板", "VIM大屏显示器");             // 设置电脑配置信息
    std::shared_ptr<Computer> computer = mer->build();        // 获取电脑对象
    std::string ans = computer->ToString();
    std::cout << ans << std::endl;                            // 打印电脑配置信息
    return 0;
}